home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 422_02 / dosutil / retab.c < prev    next >
C/C++ Source or Header  |  1994-03-20  |  5KB  |  187 lines

  1. /*
  2.  * Retabulates files to different tab stops
  3.  *
  4.  * Options:
  5.  *    -f        = Inhibit filling with spaces
  6.  *    -s        = Convert spaces to tabs where possible
  7.  *    i=n,...    = Specify input tab stops
  8.  *    o=n,... = Specify output tab stops
  9.  *
  10.  * Notes:
  11.  *    RETAB processes multiple files, and allows the tab settings to be defined
  12.  * for each file. The '-f -s i= and o=' parameters must be specified BEFORE
  13.  * the file name where they are to have effect.
  14.  *
  15.  *    If more tabs are present in the input or output file than were specified
  16.  * (using I= and O=), RETAB assumes that the tabs continue at the spacing of
  17.  * the last two stops. Therefore, if the tabs are at regular intervals, only
  18.  * the first tab stop need be given.
  19.  *
  20.  *    Both input and output tabs default to 8 space intervals.
  21.  *
  22.  *    If 'O=0' is specified, RETAB will convert all tabs in the input file to
  23.  * the appriopriate number of spaces.
  24.  *
  25.  * Examples:
  26.  *    retab i=4 tab4.fil >tab8.fil
  27.  *    retab o=4 tab8.fil >tab4.fil
  28.  *    retab i=4 o=2 tab4.file i=8 tab8.fil >tab2.fil
  29.  *    retab o=0 tab8.file >space.fil
  30.  *
  31.  * Copyright 1988-1994 Dave Dunfied
  32.  * All rights reserved.
  33.  *
  34.  * Permission granted for personal (non-commercial) use only.
  35.  *
  36.  * Compile command: cc retab -fop
  37.  */
  38. #include <stdio.h>
  39.  
  40. #define TAB_STOPS    25        /* maximum number of tab stops supported */
  41.  
  42. unsigned itabs[TAB_STOPS], otabs[TAB_STOPS];
  43.  
  44. char fill = -1, space = 0, *ptr;
  45.  
  46. main(argc, argv)
  47.     int argc;
  48.     char *argv[];
  49. {
  50.     unsigned i, j, k, l;
  51.     FILE *fp;
  52.     char flag, flag1;
  53.  
  54.     flag = -1;
  55.     flag1 = 0;
  56.  
  57. /* Install default tabs at 8 space intervals */
  58.     for(i=j=0; i < TAB_STOPS; ++i)
  59.         itabs[i] = otabs[i] = (j += 8);
  60.  
  61. /* parse the options and parameters */
  62.     for(i=1; i < argc; ++i) {
  63.         ptr = argv[i];
  64.         switch((tolower(*ptr++) << 8) | tolower(*ptr++)) {
  65.             case '-f':        /* disable fill */
  66.                 fill = 0;
  67.                 goto parm;
  68.             case '-s':        /* enable space processing */
  69.                 space = -1;
  70.                 goto parm;
  71.             case '-i':        /* specify input tabs */
  72.                 j = 0;
  73.                 do
  74.                     itabs[j++] = k = l = get_dec();
  75.                 while(*ptr++ == ',');
  76.                 if(j > 1)
  77.                     k -= itabs[j-2];
  78.                 while(j < (sizeof(itabs)/2))
  79.                     itabs[j++] = l += k;
  80.                 goto parm;
  81.             case 'o=':        /* specify output tabs */
  82.                 j = 0;
  83.                 do
  84.                     otabs[j++] = k = l = get_dec();
  85.                 while(*ptr++ == ',');
  86.                 if(j > 1)
  87.                     k -= otabs[j-2];
  88.                 while(j < (sizeof(otabs)/2))
  89.                     otabs[j++] = l += k;
  90.             parm:
  91.                 flag1 = -1;
  92.                 break;
  93.             default:
  94.                 flag = flag1 = 0;
  95.                 if(fp = fopen(argv[i], "r")) {
  96.                     do_convert(fp);
  97.                     fclose(fp); }
  98.                 else {
  99.                     fputs("RETAB: Cannot open: '", stderr);
  100.                     fputs(argv[i], stderr);
  101.                     fputs("'\n", stderr); } } }
  102.  
  103.     if(flag1)
  104.         fputs("RETAB: Trailing options have no effect!!!\n", stderr);
  105.  
  106.     if(flag)
  107.         fputs("\nUse: retab [-f -s i=n,n,n... o=n,n,n] <file*> >output_file\n\nCopyright 1988-1994 Dave Dunfield\nAll rights reserved.\n", stderr);
  108. }
  109.  
  110. /* get a decimal number from the input line */
  111. get_dec()
  112. {
  113.     unsigned value;
  114.  
  115.     value = 0;
  116.     if(isdigit(*ptr)) {                /* decimal number */
  117.         while(isdigit(*ptr))
  118.             value = (value * 10) + *ptr++ - '0'; }
  119.     else {
  120.         fputs("RETAB: Invalid number\n", stderr);
  121.         exit(-1); }
  122.  
  123.     return(value);
  124. }
  125.  
  126. /* do the tab conversion */
  127. do_convert(fp)
  128.     FILE *fp;
  129. {
  130.     unsigned ip, op, i, scount;
  131.     char chr;
  132.  
  133.     ip = op = scount = 0;
  134.  
  135.     while((chr = getc(fp)) != -1) {                /* read entire file */
  136.         if(chr == 0x09) {                        /* found a tab */
  137.             ip += scount;                        /* offset for any spaces */
  138.             for(i=0; ip >= itabs[i]; ++i);        /* next input tab position */
  139.             ip = itabs[i];
  140.             scount = 0; }
  141.         else if((chr == ' ') && space)             /* convert spaces */
  142.             ++scount;
  143.         else {                                    /* std character */
  144. /*
  145.  * if more than 1 space is encountered, or a single space
  146.  * is adjacent to a one or more tabs, convert it to tabs.
  147.  */
  148.             if((op < ip) || (scount > 1)) {
  149.                 ip += scount;
  150.                 scount = 0; }
  151. /*
  152.  * if the output pointer lags behind the input pointer
  153.  * we have received tabs or multiple spaces. Generate
  154.  * tabs in the output file to restore the position.
  155.  */
  156.             if(op < ip) {            /* we have whitespace to fill in */
  157.                 for(i=0; op >= otabs[i]; ++i);    /* next output tab position */
  158.                 while(otabs[i] <= ip) {
  159.                     putc(0x09, stdout);
  160.                     op = otabs[i++]; }
  161. /*
  162.  * Input pointer is not on an output tab stop, fill with
  163.  * spaces as nessary, to restore the correct position.
  164.  */
  165.                 if(fill) while(op < ip) {
  166.                     putc(' ', stdout);
  167.                     ++op; }
  168.                 else
  169.                     op = ip; }
  170.             ++ip;
  171. /*
  172.  * Single space received, copy to output file
  173.  */
  174.             if(scount) {
  175.                 putc(' ', stdout);
  176.                 ++op;
  177.                 ++ip;
  178.                 scount = 0; }
  179. /*
  180.  * Copy character into output file
  181.  */
  182.             putc(chr, stdout);
  183.             ++op;
  184.             if(chr == '\n')
  185.                 ip = op = 0; } }
  186. }
  187.